Changing GtkFileChooserEntry to use GtkEntryCompletion.
authorFederico Mena Quintero <federico@ximian.com>
Fri, 7 Nov 2003 23:10:19 +0000 (23:10 +0000)
committerFederico Mena Quintero <federico@src.gnome.org>
Fri, 7 Nov 2003 23:10:19 +0000 (23:10 +0000)
2003-11-07  Federico Mena Quintero  <federico@ximian.com>

Changing GtkFileChooserEntry to use GtkEntryCompletion.

* gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
a GtkListStore for the completion list.  Create a
GtkEntryCompletion and attach it to the chooser entry.
(gtk_file_chooser_entry_finalize): Unref the completion store.
(completion_match_func): New callback for the GtkEntryCompletion.
(completion_idle_callback): Fill the completion store with filenames.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkfilechooserentry.c

index d5ede926460e8c41c01270f37115d497a74d002d..1e2fd02ad27d57c931be5782787fbcedca29de0f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2003-11-07  Federico Mena Quintero  <federico@ximian.com>
+
+       Changing GtkFileChooserEntry to use GtkEntryCompletion.
+
+       * gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
+       a GtkListStore for the completion list.  Create a
+       GtkEntryCompletion and attach it to the chooser entry.
+       (gtk_file_chooser_entry_finalize): Unref the completion store.
+       (completion_match_func): New callback for the GtkEntryCompletion.
+       (completion_idle_callback): Fill the completion store with filenames.
+
 Fri Nov  7 22:55:49 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkwindow.c (gtk_window_set_role): 
index d5ede926460e8c41c01270f37115d497a74d002d..1e2fd02ad27d57c931be5782787fbcedca29de0f 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-07  Federico Mena Quintero  <federico@ximian.com>
+
+       Changing GtkFileChooserEntry to use GtkEntryCompletion.
+
+       * gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
+       a GtkListStore for the completion list.  Create a
+       GtkEntryCompletion and attach it to the chooser entry.
+       (gtk_file_chooser_entry_finalize): Unref the completion store.
+       (completion_match_func): New callback for the GtkEntryCompletion.
+       (completion_idle_callback): Fill the completion store with filenames.
+
 Fri Nov  7 22:55:49 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkwindow.c (gtk_window_set_role): 
index d5ede926460e8c41c01270f37115d497a74d002d..1e2fd02ad27d57c931be5782787fbcedca29de0f 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-07  Federico Mena Quintero  <federico@ximian.com>
+
+       Changing GtkFileChooserEntry to use GtkEntryCompletion.
+
+       * gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
+       a GtkListStore for the completion list.  Create a
+       GtkEntryCompletion and attach it to the chooser entry.
+       (gtk_file_chooser_entry_finalize): Unref the completion store.
+       (completion_match_func): New callback for the GtkEntryCompletion.
+       (completion_idle_callback): Fill the completion store with filenames.
+
 Fri Nov  7 22:55:49 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkwindow.c (gtk_window_set_role): 
index d5ede926460e8c41c01270f37115d497a74d002d..1e2fd02ad27d57c931be5782787fbcedca29de0f 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-07  Federico Mena Quintero  <federico@ximian.com>
+
+       Changing GtkFileChooserEntry to use GtkEntryCompletion.
+
+       * gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
+       a GtkListStore for the completion list.  Create a
+       GtkEntryCompletion and attach it to the chooser entry.
+       (gtk_file_chooser_entry_finalize): Unref the completion store.
+       (completion_match_func): New callback for the GtkEntryCompletion.
+       (completion_idle_callback): Fill the completion store with filenames.
+
 Fri Nov  7 22:55:49 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkwindow.c (gtk_window_set_role): 
index d5ede926460e8c41c01270f37115d497a74d002d..1e2fd02ad27d57c931be5782787fbcedca29de0f 100644 (file)
@@ -1,3 +1,14 @@
+2003-11-07  Federico Mena Quintero  <federico@ximian.com>
+
+       Changing GtkFileChooserEntry to use GtkEntryCompletion.
+
+       * gtk/gtkfilechooserentry.c (gtk_file_chooser_entry_init): Create
+       a GtkListStore for the completion list.  Create a
+       GtkEntryCompletion and attach it to the chooser entry.
+       (gtk_file_chooser_entry_finalize): Unref the completion store.
+       (completion_match_func): New callback for the GtkEntryCompletion.
+       (completion_idle_callback): Fill the completion store with filenames.
+
 Fri Nov  7 22:55:49 2003  Matthias Clasen  <maclas@gmx.de>
 
        * gtk/gtkwindow.c (gtk_window_set_role): 
index da693aba38553dd4d251807887cf1c798fc0c4a9..3111dbc50984f921edca5e85de5c95d613e0eb11 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <string.h>
 
+#include "gtkcelllayout.h"
+#include "gtkcellrenderertext.h"
 #include "gtkentry.h"
 #include "gtkfilechooserentry.h"
 
@@ -46,6 +48,8 @@ struct _GtkFileChooserEntry
 
   GtkFileFolder *current_folder;
 
+  GtkListStore *completion_store;
+
   guint in_change : 1;
   guint has_completion : 1;
 };
@@ -66,6 +70,11 @@ static void     gtk_file_chooser_entry_do_insert_text (GtkEditable      *editabl
 static void clear_completion_callback (GtkFileChooserEntry *chooser_entry,
                                       GParamSpec          *pspec);
 
+static gboolean completion_match_func (GtkEntryCompletion *comp,
+                                      const char         *key,
+                                      GtkTreeIter        *iter,
+                                      gpointer            data);
+
 static GObjectClass *parent_class;
 static GtkEditableClass *parent_editable_iface;
 
@@ -133,6 +142,24 @@ gtk_file_chooser_entry_iface_init (GtkEditableClass *iface)
 static void
 gtk_file_chooser_entry_init (GtkFileChooserEntry *chooser_entry)
 {
+  GtkEntryCompletion *comp;
+  GtkCellRenderer *renderer;
+
+  chooser_entry->completion_store = gtk_list_store_new (1, G_TYPE_STRING);
+
+  comp = gtk_entry_completion_new ();
+  gtk_entry_completion_set_model (comp, GTK_TREE_MODEL (chooser_entry->completion_store));
+  gtk_entry_completion_set_match_func (comp,
+                                      completion_match_func,
+                                      chooser_entry,
+                                      NULL);
+
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (comp), renderer, TRUE);
+  gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (comp), renderer, "text", 0);
+
+  gtk_entry_set_completion (GTK_ENTRY (chooser_entry), comp);
+
   g_signal_connect (chooser_entry, "notify::cursor-position",
                    G_CALLBACK (clear_completion_callback), NULL);
   g_signal_connect (chooser_entry, "notify::selection-bound",
@@ -144,6 +171,9 @@ gtk_file_chooser_entry_finalize (GObject *object)
 {
   GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (object);
 
+  if (chooser_entry->completion_store)
+    g_object_unref (chooser_entry->completion_store);
+
   if (chooser_entry->current_folder)
     g_object_unref (chooser_entry->current_folder);
   
@@ -157,6 +187,54 @@ gtk_file_chooser_entry_finalize (GObject *object)
   parent_class->finalize (object);
 }
 
+/* Match function for the GtkEntryCompletion */
+static gboolean
+completion_match_func (GtkEntryCompletion *comp,
+                      const char         *key,
+                      GtkTreeIter        *iter,
+                      gpointer            data)
+{
+  GtkFileChooserEntry *chooser_entry;
+  char *name;
+  gboolean result;
+
+  chooser_entry = GTK_FILE_CHOOSER_ENTRY (data);
+
+  gtk_tree_model_get (GTK_TREE_MODEL (chooser_entry->completion_store), iter, 0, &name, -1);
+  if (!name)
+    return FALSE; /* Uninitialized row, ugh */
+
+  /* We ignore the key because it is the contents of the entry.  Instead, we
+   * just use our precomputed file_part.
+   */
+
+  if (chooser_entry->file_part)
+    {
+      char *norm_file_part;
+      char *norm_name;
+
+      norm_file_part = g_utf8_normalize (chooser_entry->file_part, -1, G_NORMALIZE_ALL);
+      norm_name = g_utf8_normalize (name, -1, G_NORMALIZE_ALL);
+
+      result = (strncmp (norm_file_part, norm_name, strlen (norm_file_part)) == 0);
+
+      /* FIXME: Owen suggests first doing a case-folded comparison, then a
+       * non-case-folded one if the first one yielded more than one match.
+       */
+
+      g_free (norm_file_part);
+      g_free (norm_name);
+    }
+  else
+    result = FALSE;
+  
+
+  result = (strncmp (key, name, strlen (key)) == 0);
+
+  g_free (name);
+  return result;
+}
+
 static gboolean
 completion_idle_callback (GtkFileChooserEntry *chooser_entry)
 {
@@ -166,6 +244,8 @@ completion_idle_callback (GtkFileChooserEntry *chooser_entry)
   gchar *common_prefix = NULL;
   GtkFilePath *unique_path = NULL;
 
+  g_print ("completion_idle_callback()\n");
+
   chooser_entry->completion_idle = NULL;
 
   if (strcmp (chooser_entry->file_part, "") == 0)
@@ -183,23 +263,36 @@ completion_idle_callback (GtkFileChooserEntry *chooser_entry)
                                   &child_paths,
                                   NULL); /* NULL-GError */
 
+  chooser_entry->in_change = TRUE;
+  g_print ("Clearing list and filling it\n");
+  gtk_list_store_clear (chooser_entry->completion_store);
+
   for (tmp_list = child_paths; tmp_list; tmp_list = tmp_list->next)
     {
       GtkFileInfo *info;
+      GtkFilePath *path;
+
+      path = tmp_list->data;
       
       info = gtk_file_folder_get_info (chooser_entry->current_folder,
-                                      tmp_list->data,
+                                      path,
                                       NULL); /* NULL-GError */
       if (info)
        {
          const gchar *display_name = gtk_file_info_get_display_name (info);
-         
+         GtkTreeIter iter;
+
+         gtk_list_store_append (chooser_entry->completion_store, &iter);
+         gtk_list_store_set (chooser_entry->completion_store, &iter,
+                             0, display_name,
+                             -1);
+
          if (g_str_has_prefix (display_name, chooser_entry->file_part))
            {
              if (!common_prefix)
                {
                  common_prefix = g_strdup (display_name);
-                 unique_path = gtk_file_path_copy (tmp_list->data);
+                 unique_path = gtk_file_path_copy (path);
                }
              else
                {
@@ -222,6 +315,8 @@ completion_idle_callback (GtkFileChooserEntry *chooser_entry)
          gtk_file_info_free (info);
        }
     }
+  g_print ("List filled\n");
+  chooser_entry->in_change = FALSE;
 
   if (unique_path)
     {
@@ -290,6 +385,11 @@ gtk_file_chooser_entry_do_insert_text (GtkEditable *editable,
                                       gint        *position)
 {
   GtkFileChooserEntry *chooser_entry = GTK_FILE_CHOOSER_ENTRY (editable);
+  char *tmp;
+
+  tmp = g_strndup (new_text, new_text_length);
+  g_print ("gtk_file_chooser_entry_do_insert_text (%s)\n", tmp);
+  g_free (tmp);
   
   parent_editable_iface->do_insert_text (editable, new_text, new_text_length, position);
 
@@ -332,6 +432,8 @@ gtk_file_chooser_entry_changed (GtkEditable *editable)
   GtkFilePath *folder_path;
   gchar *file_part;
 
+  g_print ("gtk_file_chooser_entry_changed ()\n");
+
   text = gtk_entry_get_text (GTK_ENTRY (editable));
 
   if (!chooser_entry->file_system ||